home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 10 - 1994 / 10.10 Oct 94 / Prog Chal In Depth / RGBtoYUV Listing 2 < prev   
Encoding:
Text File  |  1994-09-13  |  4.5 KB  |  159 lines  |  [TEXT/R*ch]

  1. /* Prototypes */
  2.  
  3. void *RGBtoYUVInit(void);
  4.  
  5. void RGBtoYUV(unsigned char *ra, unsigned char *ga,
  6.     unsigned char *ba, unsigned char *ya,
  7.     signed char *ua, signed char *va,
  8.     unsigned long numpix, void *pd);
  9.  
  10.  
  11. /* Typedefs to tame the C language. No compiler switches, because short always 
  12.  * seems to be 16-bit... */
  13. typedef signed char signed8;
  14. typedef unsigned char unsigned8;
  15. typedef signed short signed16;
  16. typedef unsigned short unsigned16;
  17. typedef unsigned long unsigned32;
  18. typedef signed long signed32;
  19.  
  20. /* Data structure for the parallel-add algorithms */
  21. typedef struct rgb_yuv_data {
  22.     unsigned32  yuv_rg_l[65536L];
  23.     unsigned32  yuv_rg_h[65536L];
  24.     unsigned32  yuv_b_l[256];
  25.     unsigned32  yuv_b_h[256];
  26. } rgb_yuv_data;
  27.  
  28. Transform matrix: Determines the orientation of the RGB color cube within YUV space, and the relative intensities of R, G, and B.
  29. NOTE: Whenever the matrix is changed, error analysis has to be done to determine if 20 bits is still enough accuracy to determine the rounding direction of results!
  30.  
  31. signed32 ml[] = {
  32.   2508194L,  4924113L,   956301L,
  33.  -1415459L, -2778845L,  4194304L,
  34.   4194304L, -3512206L,  -682098L };
  35.  
  36. RGBtoYUVInit
  37. /* Parallel addition, 64-bit math version.
  38.  * Hi format is 00CVVVVVVVVvvvvvvvvvvvvCUUUUUUUU
  39.  * Lo format is uuuuuuuuuuuuYYYYYYYYyyyyyyyyyyyy
  40.  */
  41. void *RGBtoYUVInit()
  42. {
  43.     rgb_yuv_data  *p;
  44.     Handle        h;
  45.     OSErr         err;
  46.     unsigned16    r, g, b;
  47.     signed32      index;
  48.     signed32      yl, ul, vl;
  49.     unsigned32    yi;
  50.     signed32      ui, vi;
  51.     unsigned32    round_adjust = 0x7fe;
  52.     unsigned32    lo12 = 0x0fffL;
  53.     unsigned32    lo20 = 0xfffffL;
  54.     unsigned32    datasize = sizeof(rgb_yuv_data);
  55.  
  56.     h = TempNewHandle(datasize, &err);
  57.     HLock(h);
  58.     p = *((rgb_yuv_data **) h);
  59.  
  60.     for (r=0; r<256; r++) {
  61.         for (g=0; g<256; g++) {
  62.             yl = ml[0] * ((signed32) r)
  63.                          + ml[1] * ((signed32) g);
  64.             ul = ml[3] * ((signed32) r)
  65.                          + ml[4] * ((signed32) g);
  66.             vl = ml[6] * ((signed32) r)
  67.                          + ml[7] * ((signed32) g);
  68.  
  69.             yi = (yl + 1024)>>11L; yi += round_adjust;
  70.             ui = (ul + 1024)>>11L; ui += round_adjust;
  71.             vi = (vl + 1024)>>11L; vi += round_adjust;
  72.  
  73.             index = (((long)r)<<8L) | ((long)g);
  74.  
  75.             (p->yuv_rg_h)[index] =
  76.                 ((vi&lo20)<<9L) | ((ui&lo20)>>12L);
  77.  
  78.             (p->yuv_rg_l)[index] = ((ui&lo12)<<20L) | yi;
  79.        }
  80.     }
  81.  
  82.     for (b=0; b<256; b++) {
  83.         yl = ml[2] * ((signed32) b);
  84.         ul = ml[5] * ((signed32) b);
  85.         vl = ml[8] * ((signed32) b);
  86.  
  87.         yi = (yl + 1024)>>11L;
  88.         ui = (ul + 1024)>>11L;
  89.         vi = (vl + 1024)>>11L;
  90.  
  91.         index = b;
  92.         p->yuv_b_h[index] =
  93.                     ((vi&lo20)<<9L) | ((ui&lo20)>>12L);
  94.  
  95.         p->yuv_b_l[index] = ((ui&lo12)<<20L) + yi;
  96.    }
  97.  
  98.     return ((void *)p);
  99. }
  100.  
  101.  
  102.  
  103. //RGBtoYUV for 64-bit math version.
  104. It’s hard to read because the instructions were reordered to minimize pipeline stalls from result dependencies on the ‘040.
  105.  
  106. void RGBtoYUV(unsigned char *ra, unsigned char *ga,
  107.     unsigned char *ba, unsigned char *ya,
  108.     signed char *ua, signed char *va,
  109.     unsigned long numpix, void *pd)
  110. {
  111.     register signed32      index;
  112.     register signed32      i2;
  113.              unsigned32    i;
  114.     register unsigned32    hi, lo_rg, lo;
  115.     register unsigned char *yar = ya;
  116.     register signed char   *var = va;
  117.     register unsigned8     *p;
  118.  
  119.     for(i=0; i<numpix; i++) {
  120.         p = (unsigned8 *) pd;
  121.         index = ((long)(*ra));              /* Compute indexes */
  122.         i2 = ((long)(*ba));
  123.         index <<= 8L;
  124.         index += ((long)(*ga));
  125.         i2 <<= 2L;
  126.         index <<= 2L;
  127.         ga++;                               /* Increment src ptrs */
  128.         p += index;
  129.         lo_rg = *((unsigned32 *)(p)); /* yuv_rg, low */
  130.         p += 262144L;
  131.         ra++;
  132.         hi = *((unsigned32 *)(p));        /* yuv_rg, high */
  133.         index -= i2;
  134.         p += 262144L;
  135.         ba++;
  136.         p -= index;
  137.         lo = lo_rg + *((unsigned32 *)(p));
  138.         hi += *((unsigned32 *)(p+1024L));
  139.         if (lo < lo_rg) {
  140.             hi++;                                   /* there was a carry! */
  141.             lo >>= 6L;                              /* Store the results */
  142.             *ua = hi;
  143.             lo >>= 6L;
  144.             *yar++ = lo;
  145.             hi >>= 21L;
  146.             ua++;
  147.             *var++ = hi;
  148.         } else {
  149.             lo >>= 6L;                              /* Store the results */
  150.             *ua = hi;
  151.             lo >>= 6L;
  152.             *yar++ = lo;
  153.             hi >>= 21L;
  154.             ua++;
  155.             *var++ = hi;
  156.         }
  157.     }
  158. }
  159.